package com.ruoyi.system.service.impl;

import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.DbInfo;
import com.ruoyi.system.mapper.DbInfoMapper;
import com.ruoyi.system.service.IDbInfoService;
import org.postgresql.util.PSQLException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.*;
import java.util.List;
import java.util.Properties;
import org.postgresql.Driver;

/**
 * 数据库信息Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-09-02
 */
@Service
public class DbInfoServiceImpl implements IDbInfoService 
{
    @Autowired
    private DbInfoMapper dbInfoMapper;

    /**
     * 查询数据库信息
     * 
     * @param dbId 数据库信息主键
     * @return 数据库信息
     */
    @Override
    public DbInfo selectDbInfoByDbId(Long dbId)
    {
        return dbInfoMapper.selectDbInfoByDbId(dbId);
    }

    /**
     * 查询数据库信息列表
     * 
     * @param dbInfo 数据库信息
     * @return 数据库信息
     */
    @Override
    public List<DbInfo> selectDbInfoList(DbInfo dbInfo)
    {
        return dbInfoMapper.selectDbInfoList(dbInfo);
    }

    /**
     * 新增数据库信息
     * 
     * @param dbInfo 数据库信息
     * @return 结果
     */
    @Override
    public int insertDbInfo(DbInfo dbInfo)
    {
        dbInfo.setCreateTime(DateUtils.getNowDate());

        // 保存的时候 存部门信息和用户信息
        SysUser currentUser = ShiroUtils.getSysUser();
        dbInfo.setUserId(currentUser.getUserId());
        dbInfo.setDeptId(currentUser.getDeptId());

        return dbInfoMapper.insertDbInfo(dbInfo);
    }

    /**
     * 修改数据库信息
     * 
     * @param dbInfo 数据库信息
     * @return 结果
     */
    @Override
    public int updateDbInfo(DbInfo dbInfo)
    {
        dbInfo.setUpdateTime(DateUtils.getNowDate());
        return dbInfoMapper.updateDbInfo(dbInfo);
    }

    /**
     * 批量删除数据库信息
     * 
     * @param dbIds 需要删除的数据库信息主键
     * @return 结果
     */
    @Override
    public int deleteDbInfoByDbIds(String dbIds)
    {
        return dbInfoMapper.deleteDbInfoByDbIds(Convert.toStrArray(dbIds));
    }

    @Override
    public int selectSuccessNumber(Long userId) {
        return dbInfoMapper.selectSuccessNumber(userId);
    }

    /**
     * 删除数据库信息信息
     * 
     * @param dbId 数据库信息主键
     * @return 结果
     */
    @Override
    public int deleteDbInfoByDbId(Long dbId)
    {
        return dbInfoMapper.deleteDbInfoByDbId(dbId);
    }

    @Override
    public String testGaussDBConnection(DbInfo dbInfo) {
        String ip = dbInfo.getIpAddr();
        int port = dbInfo.getPort();
        String dbName = dbInfo.getNaDb();
        String username = dbInfo.getUsername();
        String password = dbInfo.getPassword();

        // 1. 参数校验
        if (StringUtils.isEmpty(ip) || StringUtils.isEmpty(dbName) || StringUtils.isEmpty(username) || StringUtils.isEmpty(password) || port <= 0 || port > 65535) {
            return "参数校验失败";
        }

        // 2. 初始化JDBC资源
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {
            // ① 加载JDBC驱动（PostgreSQL驱动会自动注册，可省略Class.forName）
            Class.forName("org.postgresql.Driver"); // 兼容低版本驱动，可选加

            // ② 构建JDBC连接URL
            String jdbcUrl = String.format("jdbc:postgresql://%s:%d/%s", ip, port, dbName);

            // ③ 建立数据库连接（超时时间建议设置，避免无限等待）
            conn = DriverManager.getConnection(jdbcUrl, username, password);
            // 可选：设置连接超时（需驱动支持，部分版本可能不生效）
            // conn.setNetworkTimeout(Executors.newSingleThreadExecutor(), 5000); // 5秒超时

            // ④ 验证连接有效性（执行简单SQL：SELECT 1，高斯数据库支持）
            String testSql = "SELECT 1 AS connect_test";
            pstmt = conn.prepareStatement(testSql);
            rs = pstmt.executeQuery();

            // ⑤ 检查SQL执行结果
            if (rs.next()) {
                int result = rs.getInt("connect_test");
                if (result == 1) {
                    return "";
                }
            }
            return "高斯数据库连接测试失败：执行SQL无有效结果";
        } catch (ClassNotFoundException e) {
            return "加载高斯数据库JDBC驱动失败（驱动未引入或路径错误）";
        } catch (Exception e) {
            String errorMsg = e.getMessage();
            if (errorMsg.contains("Connection refused")) {
                return "连接被拒：IP=" + ip + "或端口=" + port + "错误，检查网络";
            } else if (errorMsg.contains("password authentication failed") || errorMsg.contains("Invalid username/password")) {
                return "认证失败：用户名或密码错误";
            } else if (errorMsg.contains("database \"" + dbName + "\" does not exist")) {
                return "数据库不存在：" + dbName;
            } else if (errorMsg.contains("timed out")) {
                return "连接超时：请检查：IP 与 端口（如果IP与端口无误，则需要考虑网络策略是否已打通）";
            } else {
                return "连接异常原因：" + errorMsg;
                // 捕获所有连接异常（如IP不可达、端口错误、账号密码错误、权限不足等）
//                return "高斯数据库连接测试异常，可能原因：IP不可达、端口错误、账号密码错误、权限不足等：" + errorMsg;
            }
        } finally {
            // 3. 关闭JDBC资源（按ResultSet→PreparedStatement→Connection顺序关闭，避免资源泄漏）
            try {
                if (rs != null) rs.close();
                if (pstmt != null) pstmt.close();
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                // 资源关闭异常不影响主结果，仅做日志记录
                e.printStackTrace();
            }
        }
    }

    /*public String testHuaweiGaussDBConnection(DbInfo dbInfo) {
        String ip = dbInfo.getIpAddr();
        int port = dbInfo.getPort();
        String dbName = dbInfo.getNaDb();
        String username = dbInfo.getUsername();
        String password = dbInfo.getPassword();

        // 1. 参数校验
        if (StringUtils.isEmpty(ip) || StringUtils.isEmpty(dbName) || StringUtils.isEmpty(username) || StringUtils.isEmpty(password) || port <= 0 || port > 65535) {
            return "参数校验失败";
        }

        // 2. 初始化JDBC资源
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {
            // ① 加载华为高斯数据库JDBC驱动
            Class.forName("com.huawei.gauss200.jdbc.Driver");

            // ② 构建华为高斯数据库JDBC连接URL
            // 格式：jdbc:gaussdb://<host>:<port>/<database>
            String jdbcUrl = String.format("jdbc:gaussdb://%s:%d/%s", ip, port, dbName);

            // ③ 建立数据库连接（可添加额外连接参数，如超时设置）
            Properties props = new Properties();
            props.setProperty("user", username);
            props.setProperty("password", password);
            props.setProperty("connectTimeout", "5000"); // 连接超时设置为5秒
            conn = DriverManager.getConnection(jdbcUrl, props);

            // ④ 验证连接有效性（执行简单SQL测试）
            String testSql = "SELECT 1 AS connect_test";
            pstmt = conn.prepareStatement(testSql);
            rs = pstmt.executeQuery();

            // ⑤ 检查SQL执行结果
            if (rs.next()) {
                int result = rs.getInt("connect_test");
                if (result == 1) {
                    return ""; // 连接成功返回空字符串
                }
            }
            return "高斯数据库连接测试失败：执行SQL无有效结果";
        } catch (ClassNotFoundException e) {
            return "加载高斯数据库JDBC驱动失败（请确认已引入华为高斯数据库驱动包）";
        } catch (SQLException e) {
            // 捕获SQL异常，返回具体错误信息
            return "高斯数据库连接测试异常：" + e.getMessage();
        } catch (Exception e) {
            return "高斯数据库连接测试发生未知异常：" + e.getMessage();
        } finally {
            // 3. 关闭JDBC资源
            try {
                if (rs != null) rs.close();
                if (pstmt != null) pstmt.close();
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (SQLException e) {
                // 资源关闭异常不影响主结果，仅做日志记录
                e.printStackTrace();
            }
        }
    }*/

    public String testHuaweiGaussDBConnection(DbInfo dbInfo) {
        // 1. 参数校验
        if (dbInfo == null) {
            return "参数错误：DbInfo对象不能为空";
        }
        String ip = dbInfo.getIpAddr();
        int port = dbInfo.getPort();
        String dbName = dbInfo.getNaDb();
        String username = dbInfo.getUsername();
        String password = dbInfo.getPassword();

        if (StringUtils.isEmpty(ip) || StringUtils.isEmpty(dbName) ||
                StringUtils.isEmpty(username) || StringUtils.isEmpty(password) ||
                port <= 0 || port > 65535) {
            return "参数错误：IP、数据库名、用户名、密码不能为空，端口必须在1-65535之间";
        }

        // 2. 验证PostgreSQL驱动是否可用
        Driver pgDriver;
        try {
            pgDriver = new Driver(); // 实例化PostgreSQL驱动
        } catch (Exception e) {
            return "驱动错误：org.postgresql.Driver类不存在，请检查JAR包是否正确";
        }

        // 3. 构建PostgreSQL兼容的URL（DWS兼容该格式）
        // 注意：DWS兼容PostgreSQL协议，URL必须用jdbc:postgresql://前缀
        String jdbcUrl = String.format("jdbc:postgresql://%s:%d/%s", ip, port, dbName);

        // 4. 检测驱动是否支持该URL（PostgreSQL驱动仅支持jdbc:postgresql://）
        try {
            if (!pgDriver.acceptsURL(jdbcUrl)) {
                return "URL格式错误：PostgreSQL驱动仅支持jdbc:postgresql://ip:port/dbName，当前URL：" + jdbcUrl;
            }
        } catch (PSQLException e) {
            throw new RuntimeException(e);
        }

        // 5. 建立连接并测试
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            Properties props = new Properties();
            props.setProperty("user", username);
            props.setProperty("password", password);
            // DWS兼容PostgreSQL的SSL配置（按需开启）
            props.setProperty("ssl", "false"); // 先禁用SSL简化测试
            props.setProperty("loginTimeout", "10"); // 登录超时10秒

            // 用PostgreSQL驱动连接DWS
            conn = pgDriver.connect(jdbcUrl, props);
            if (conn == null) {
                return "连接失败：驱动不支持该URL或数据库拒绝连接";
            }

            // 执行验证SQL（DWS支持标准PostgreSQL语法）
            String testSql = "SELECT 1 AS connect_test";
            pstmt = conn.prepareStatement(testSql);
            rs = pstmt.executeQuery();

            if (rs.next() && rs.getInt("connect_test") == 1) {
                return ""; // 连接成功
            }
            return "测试失败：验证SQL无有效结果";

        } catch (SQLException e) {
            String errorMsg = e.getMessage();
            if (errorMsg.contains("Connection refused")) {
                return "连接被拒：IP=" + ip + "或端口=" + port + "错误，检查网络";
            } else if (errorMsg.contains("password authentication failed") || errorMsg.contains("Invalid username/password")) {
                return "认证失败：用户名或密码错误";
            } else if (errorMsg.contains("database \"" + dbName + "\" does not exist")) {
                return "数据库不存在：" + dbName;
            } else if (errorMsg.contains("timed out")) {
                return "连接超时：请检查：IP 与 端口（如果IP与端口无误，则需要考虑网络策略是否已打通）";
            } else {
                return "连接异常原因：" + errorMsg;
            }
        } catch (Exception e) {
            return "未知错误：" + e.getMessage();
        } finally {
            // 关闭资源
            try {
                if (rs != null) rs.close();
                if (pstmt != null) pstmt.close();
                if (conn != null && !conn.isClosed()) conn.close();
            } catch (SQLException e) {}
        }
    }

}
